全局作用域

  1. 在<script></script>标签里,即为全局作用域
  2. 在函数体之外,<script>标签内声明的变量就是全局变量
  3. 全局作用域内的变量可以在任何其他的作用域访问和修改。

    <script>
        vara = 0;
        function func1(){
            a = 1;
            console.log(a);     
            console.log(b);     
        };
        func1();     // 1  b is not defined
    </script>
    
    <script>
        varb = 2;        
        func1();    // 1 2
    </script>
    

局部作用域

  1. 一个函数体就是一个新的局部作用域。
  2. 函数内部定义的变量在局部作用域内。
  3. 函数外部作用域不能访问内部作用域的变量。
  4. 每个函数有不同的作用域,在其他函数中是不可以访问的(一个函数访问另一个函数变量的时候,通过传递参数)。

    <script>       
        function func1(){
            var a = 0;  
        };
    
        function func2(){
            var b = 2;             
            console.log(b);
            console.log(a);
        };
    
        func2();    // 2   a is not defined
    
        console.log(b); // b is not defined 
    </script>     
    

作用域链

  1. 函数作用域里面访问一个变量,先从自身开始找,如果没有,就依次往上一级作用域查找,直到全局作用域,全局作用没有就报错。
  2. 当我们处于某一个作用域里面,修改某个变量值的时,先修改自身作用域,如果没有就依次修改上一个作用域。

       
    <script>       
        var a = 10;
        var b = 30;
        function func(){
            var a = 20; // 声明局部变量a
            a = 2;      // 改变局部变量a
            b = 3;      // 本作用域中无b变量,会依次更改上层作用域中的变量
            c = 4;      // 给未被声明的变量赋值,会泄露带window中
            d = 5;      // (未报错?)本作用域中无d变量,会依次更改上层作用域中的变量,全部没有则报错
            console.log(a);
        };
    
        console.log(b);     // 30       全局变量b
        // console.log(c);     //         c is not defined
        func();             // 2        局部变量a
        console.log(a);     // 10       全局变量a
        console.log(b);     // 3        被下层作用域修改的变量b
        console.log(c);     // 4        被泄露到window中的变量c
    </script>
    

delete

  1. 删除未声明的变量,但是不可以删除已经声明的变量

    <script>       
        var a = 10;
        b = 30;
       
        delete a;
        delete b;
    
        console.log(a);     // 10
        console.log(b);     // b is not defined
    </script>
    

块作用域(ES6新增)

  1. let , const 不仅仅是声明变量的区别,它们还有支持块作用域的机制(注意:不是大括号,if,switch,for产生的块)
  2. let,consts声明的变量不会泄露到顶层对象,只能声明之后再使用,var可以先赋值,在声明

    <script>
        if(true){
            var a = 10;
            let b = 20;
            const c = 30;
        };
    
        console.log(a);     // 10
        console.log(b);     // b is not defined
        console.log(c);     // b is not defined
    </script>
    

注意

  • 多个作用域问题

    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    
    <script>
    
        var aDiv = document.getElementsByTagName("div");
    
        for(var i = 0; i < 5; i++){  
    
            aDiv[i].index = i;      // 解决i使用var声明时,在函数作用域中的变量i一直是最后执行结果的问题
    
            aDiv[i].onclick = function(){     
    
                console.log(i);             // i使用var声明,结果一直都是5, i使用let声明,结果是0 1 2 3 4 
                                           // 函数体和for循环不处于同一个作用域,需等前一个作用域执行完,才会执行本作用域
                console.log(this.index);    // 0 1 2 3 4 
            }
        }
    
    </script>
    

豆爹
6 声望0 粉丝